home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
AMICUS
/
AMICUS02.ADF
/
Asm
/
SystemVprintf.asm
< prev
next >
Wrap
Assembly Source File
|
1989-05-30
|
31KB
|
1,083 lines
RORG 0
*
* Unix System 5 compatible printf, fprintf, sprintf functions, ported to
* commodore Amiga, 12/17/85 Gary Sarff. The only bug is that the
* %f format specification may not work properly since Amiga lacks the
* function fcvt(), instead a call to ecvt is used. It really should be
* fixed to use gcvt() and perhaps a temporary buffer to make it "look" like
* fcvt() but I don't have time now to do it.
* The reason this port was done was that Lattice C's printf on the Amiga
* lacks the ability to use an * as a field width or precision to allow
* run-time specification of field width or precision. These functions have
* that capability.
*
* To use this from a C program, you must #include <stdio.h> since these
* functions use the address of the i/o buffer __iob,
* and you should declare these functions to be:
* extern int u5printf();
* extern int u5fprintf();
* extern int u5sprintf();
* You may then call them with any arbitrary number of arguments, just like
* the builtin printf, fprintf, sprintf functions.
* You can also access the gcvt() function yourself by declaring it as
* extern char *gcvt();
* and calling it with args: gcvt(value, ndigits, buf);
* where declarations double value;
* int ndigits; /* the number of digits shown*/
* char *buf; /* address of the buffer to
* store result in. gcvt also
* returns the address of this
* buffer */
* sccs_ctnrl == "5/15/81 (Berkley) @(#)printf.s v3.8"
*
* This file had to be modified extensively in places to allow for the
* difference in the structure of __iob on the Amiga from the Unix __iob
* structure for which this was originally written.
* Only some places in __strout have comments to mark modifications. There
* wasn't time to comment all of them.
*
XDEF _u5printf
XDEF _u5fprintf
XDEF _u5sprintf
XDEF _gcvt
* make functions visible to outside world.
XREF __iob
XREF __flsbf
XREF _ecvt
* use above functions from Lattice libraries.
* called with u5printf(<format_string>,<arglist>)
_u5printf:
link a6,#-4
move.l #__iob+$14,(sp) * modified from __iob+10, Lattice iob is
* bigger and has different elements.
pea 12(a6) * address of first value to print on stack
move.l 8(a6),-(sp) * address of the format control string.
bsr.l __doprnt * let __doprnt do all the work.
addq.l #8,sp
move.b __iob+$20,d0 * modified from __iob+$C, this is where
* * the error flag, if any is kept.
ext.l d0 * also return status code to the caller.
btst #5,d0 * 2^5 (32) is an error indicator.
beq.s u5pr30 * no error.
moveq.l #-1,d0 * oops, user screwed up, signal error.
u5pr2c:
unlk a6
rts
u5pr30:
moveq.l #0,d0 * signal no error.
bra.s u5pr2c
*
* called with u5fprintf(<stream>,<format_string>,<arg_list>)
*
_u5fprintf:
link a6,#-4
move.l 8(a6),(sp) * address of stream.
pea 16(a6) * address of first value to print.
move.l 12(a6),-(sp) * address of format string.
bsr.s __doprnt * we're tired today, __doprnt do it!
addq.l #8,sp
movea.l 8(a6),a0
move.w 12(a0),d0
ext.l d0
btst #5,d0 * did fprintf fail?
beq.s u5fpr2e
moveq.l #-1,d0 * yes signal an error to unfortunate user
u5fpr2a:
unlk a6
rts
u5fpr2e:
moveq.l #0,d0
bra.s u5fpr2a
*
* called with u5sprintf(<addr_of_buf>,<format_string>,<arg_list>)
*
_u5sprintf:
link a6,#-16
moveq.l #$42,d0
move.w d0,-4(a6)
move.l 8(a6),-12(a6)
move.l #$7fff,-16(a6)
pea -16(a6)
pea 16(a6)
move.l 12(a6),-(sp)
bsr.s __doprnt
lea 12(sp),sp
subq.l #1,-16(a6)
blt.s u5spr48
move.l -12(a6),d0 * skip one past end of string and
addq.l #1,-12(a6) * make sure it is terminated by a
movea.l d0,a0 * hex 00 character.
moveq.l #0,d0
move.b d0,(a0) * now it is.
ext.w d0
ext.l d0
bra.s u5spr58
u5spr48:
pea -16(a6)
moveq.l #0,d0 * flush the buffer to the null port
move.l d0,-(sp) * since doprnt actually puts stuff in
jsr __flsbf * buffer and we let it do all the work.
addq.l #8,sp
u5spr58:
move.l 8(a6),d0
unlk a6
rts
*
* The workhorse of this whole show.
* Just muddle through the format string a char at a time looking for
* % format specifiers and backslash \n,\t,\e etc to handle the special
* characters.
*
__doprnt:
link a6,#-164
movem.l d0/d2-d7/a2-a5,-(sp)
movea.l 8(a6),a5 * address of the format string
movea.l 12(a6),a4 * list head of argument list
movea.l 16(a6),a3 * address of our buffer (__iob)
dop18:
lea -140(a6),a0
movea.l a0,a2 * start address of our work buffer.
bra.l dop44c * make sure format string isn't null.
dop22:
move.b d7,(a2)+ * top of loop that puts chars in buff.
bra.l dop44c
dop28:
moveq.l #$25,d0 * is it a %?
cmp.b d7,d0
bne.s dop22 * no, its something else so buf it.
lea -140(a6),a0 * address of buffer.
cmpa.l a0,a2 * have we actually written anything yet?
beq.s dop58 * no we haven't.
move.l a3,(sp) * address of destination buffer.
moveq.l #0,d0 * 0 for strout.
move.l d0,-(sp)
lea -140(a6),a0 * address of our work buffer.
move.l a2,d0
sub.l a0,d0 * get length of string so far.
move.l d0,-(sp)
pea -140(a6) * plus address of buffer.
bsr.l __strout * tally ho!
lea 12(sp),sp
lea -140(a6),a0
movea.l a0,a2
dop58:
moveq.l #0,d0
move.b d0,-152(a6) * assume no left justification.
moveq.l #0,d4
moveq.l #$20,d0
move.b d0,-151(a6)
moveq.l #$2D,d0 * is it a -, (left justification)
cmp.b (a5),d0
bne.s dop72 * no its not.
addq.b #1,-152(a6) * signal left justify needed.
addq.l #1,a5 * point to next char in format str.
dop72:
moveq.l #$30,d0 * is it a 0?
cmp.b (a5),d0
bne.s dop7e * no.
move.b d0,-151(a6)
addq.l #1,a5
dop7e:
moveq.l #$2A,d0 * is it an asterisk.
cmp.b (a5),d0 * if it is handle run-time field
beq.s dopa4 * width/precision specification.s
moveq.l #0,d5
dop86:
move.b (a5)+,d0 * eat up the digits of a field width
ext.w d0 * precision spec.
moveq.l #$30,d1 * do a simple:
sub.w d1,d0 * val=10*val + a5++ until we find
ext.l d0 * something that's not a digit.
move.l d0,d6
blt.s dopb4 * something less than 0? exit.
moveq.l #9,d0
cmp.l d6,d0
blt.s dopb4 * something greater than 9? exit
add.l d5,d5 * multiply by 10.
add.l d5,d6
asl.l #2,d5
add.l d6,d5
bra.s dop86 * round and round we go!
dopa4:
addq.l #1,a5
move.b (a5)+,d0
ext.w d0
moveq.l #$30,d1
sub.w d1,d0
move.w d0,d6
ext.l d6
move.l (a4)+,d5
dopb4:
moveq.l #0,d0 * handle the precision part here.
move.b d0,-153(a6) * just like the field width above.
moveq.l #$30,d0
add.l d0,d6
moveq.l #$2E,d0 * look for a decimal point
cmp.l d6,d0
bne.s dop104 * none, must not be any precision.
moveq.l #$2A,d0 * is precision a *
cmp.b (a5),d0
beq.s dopf4 * Oh boy, do some more work for stars
moveq.l #0,d4
bra.s dope0
dopce:
moveq.l #9,d0 * eat up the digits. Yummy!
cmp.l d6,d0
blt.s dopee
addq.b #1,-153(a6)
add.l d4,d4
add.l d4,d6
asl.l #2,d4
add.l d6,d4
dope0:
move.b (a5)+,d0
ext.w d0
moveq.l #$30,d1
sub.w d1,d0
ext.l d0
move.l d0,d6
bge.s dopce
dopee:
moveq.l #$30,d0
add.l d0,d6
bra.s dop104
dopf4:
addq.l #1,a5 * handle star precision.
move.b (a5)+,d0
ext.w d0
ext.l d0
move.l d0,d6
addq.b #1,-153(a6)
move.l (a4)+,d4 * get an arg for it.
dop104:
move.l d6,d0
moveq.l #$65,d1 * is it a little e?
cmp.l d1,d0
beq.l dop350 * do e format.
bgt.s dop14e
moveq.l #$4F,d1 * O format?
cmp.l d1,d0
beq.l dop1e6
bgt.s dop130
moveq.l #$25,d1 * another % symbol, means we print one.
cmp.l d1,d0 * literally I mean.
beq.l dop448
moveq.l #$44,d1 * is it a D format?
cmp.l d1,d0
beq.l dop1f0 * do %d format for ints.
moveq.l #$4C,d1 * is there an l, that means "long".
cmp.l d1,d0
beq.s dop18e
dop130:
moveq.l #$55,d1 * U format. Unsigned Octal, (weird)
cmp.l d1,d0
beq.s dop1ae
moveq.l #$58,d1 * X format. Hex Hex Hex.
cmp.l d1,d0
beq.l dop1ec
moveq.l #$63,d1 * C format, its a char!
cmp.l d1,d0
beq.l dop22c
moveq.l #$64,d1 * another d, little this time.
cmp.l d1,d0 * so go to same place as Big D.
beq.l dop1f0
dop14e:
moveq.l #$6F,d1 * little o, for octal.
cmp.l d1,d0
beq.l dop1e6
bgt.s dop16e
moveq.l #$66,d1 * little f, for float ('scuse me)
cmp.l d1,d0
beq.l dop2ca
moveq.l #$67,d1 * little g, float/scientific.
cmp.l d1,d0
beq.l dop420
moveq.l #$6C,d1 * little l, its a long one.
cmp.l d1,d0
beq.s dop18e
dop16e:
moveq.l #$72,d1 * little r, remote string.
cmp.l d1,d0
beq.l dop2c2
moveq.l #$73,d1 * little s, its a string.
cmp.l d1,d0
beq.l dop29a
moveq.l #$75,d1 * little u, unsigned octal again.
cmp.l d1,d0
beq.s dop1ae
moveq.l #$78,d1 * little x, hex.
cmp.l d1,d0
beq.s dop1ec
bra.l dop44c
*
* these are the work routines that format each of the data types.
*
dop18e:
move.b (a5)+,d0
ext.w d0
ext.l d0
moveq.l #$64,d1
cmp.l d1,d0
beq.s dop1f0
moveq.l #$6F,d1
cmp.l d1,d0
beq.s dop1e6
moveq.l #$75,d1
cmp.l d1,d0
beq.s dop1ae
moveq.l #$78,d1
cmp.l d1,d0
beq.s dop1ec
subq.l #1,a5
dop1ae:
move.l (a4)+,d2
moveq.l #$A,d3
dop1b2:
tst.l d2
bne.s dop1be
tst.l d4
bne.s dop1be
moveq.l #$30,d0
move.b d0,(a2)+
dop1be:
lea -150(a6),a0
move.l a0,-4(a6)
bra.s dop210
dop1c8:
move.l d3,(sp)
move.l d2,-(sp)
jsr _uldivr
addq.l #4,sp
move.l d0,d2
move.l _ldivrm,d6
moveq.l #$A,d0
cmp.l d6,d0
ble.s dop202
moveq.l #$30,d0
bra.s dop204
dop1e6:
moveq.l #8,d3
dop1e8:
move.l (a4)+,d2
bra.s dop1b2
dop1ec:
moveq.l #$10,d3
bra.s dop1e8
dop1f0:
moveq.l #$A,d3
tst.l (a4)
bge.s dop1e8
moveq.l #$2D,d0
move.b d0,(a2)+
move.l (a4)+,d0
neg.l d0
move.l d0,d2
bra.s dop1b2
dop202:
moveq.l #$57,d0
dop204:
add.l d6,d0
movea.l -4(a6),a0
move.b d0,(a0)
addq.l #1,-4(a6)
dop210:
tst.l d2
bne.s dop1c8
dop214:
lea -150(a6),a0
move.l -4(a6),d0
cmp.l a0,d0
bls.s dop250
subq.l #1,-4(a6)
movea.l -4(a6),a0
move.b (a0),(a2)+
bra.s dop214
dop22c:
movea.l a4,a0
addq.l #4,a4
move.l a0,-4(a6)
moveq.l #0,d6
bra.s dop24a
dop238:
move.l -4(a6),d0
addq.l #1,-4(a6)
movea.l d0,a0
move.b (a0),(a2)+
bne.s dop248
subq.l #1,a2
dop248:
addq.l #1,d6
dop24a:
moveq.l #4,d0
cmp.l d6,d0
bgt.s dop238
dop250:
lea -140(a6),a0
move.l a0,-4(a6)
dop258:
move.l a2,d0
sub.l -4(a6),d0
move.l d5,d1
sub.l d0,d1
move.l d1,d6
bge.s dop268
moveq.l #0,d6
dop268:
tst.b -152(a6)
bne.s dop274
move.l d6,d0
neg.l d0
move.l d0,d6
dop274:
move.b -151(a6),d0
ext.w d0
ext.l d0
move.l d0,(sp)
move.l a3,-(sp)
move.l d6,-(sp)
move.l a2,d0
sub.l -4(a6),d0
move.l d0,-(sp)
move.l -4(a6),-(sp)
bsr.l __strout
lea 16(sp),sp
bra.l dop18
dop29a:
move.l (a4)+,-4(a6)
bne.s dop2a8
move.l #__lastbuf+4,-4(a6)
dop2a8:
move.l d4,d6
bne.s dop2b2
move.l #$7fff,d6
dop2b2:
movea.l -4(a6),a2
dop2b6:
tst.b (a2)
beq.s dop258
subq.l #1,d6
blt.s dop258
addq.l #1,a2
bra.s dop2b6
dop2c2:
movea.l (a4),a4
movea.l (a4)+,a5
bra.l dop44c
dop2ca:
tst.b -153(a6)
bne.s dop2d2
moveq.l #6,d4
dop2d2:
pea -8(a6) * do the f specification.
pea -12(a6)
move.l d4,-(sp)
move.l 4(a4),-(sp)
move.l (a4),-(sp)
jsr _ecvt * kludge, lattice doesn't have fcvt.
lea 20(sp),sp
move.l d0,-4(a6)
addq.l #8,a4
tst.l -8(a6)
beq.s dop2fc
moveq.l #$2D,d0 * if num is <0 put a - in front of buf.
move.b d0,(a2)+
dop2fc:
move.l -12(a6),d6
bgt.s dop308
moveq.l #$30,d0 * if need to make sure one 0 shows.
move.b d0,(a2)+
bra.s dop316
dop308:
movea.l -4(a6),a0
move.b (a0),(a2)+
addq.l #1,-4(a6)
subq.l #1,d6
bgt.s dop308
dop316:
move.l d4,d6
beq.s dop31e
moveq.l #$2E,d0 * place the decimal point in the right spot
move.b d0,(a2)+
dop31e:
move.l -12(a6),d0
neg.l d0
move.l d0,-12(a6)
ble.s dop338
dop32a:
subq.l #1,d6
blt.s dop338
moveq.l #$30,d0
move.b d0,(a2)+
subq.l #1,-12(a6)
bgt.s dop32a
dop338:
tst.l d6
ble.l dop250
dop33e:
subq.l #1,d6
blt.l dop250
movea.l -4(a6),a0
move.b (a0),(a2)+
addq.l #1,-4(a6)
bra.s dop33e
dop350:
tst.b -153(a6)
bne.s dop35a
moveq.l #6,d4
bra.s dop35c
dop35a:
addq.l #1,d4
dop35c:
pea -8(a6) * do e format, see f format above for
pea -12(a6) * some really informative comments.
move.l d4,-(sp)
move.l 4(a4),-(sp)
move.l (a4),-(sp)
jsr _ecvt
lea 20(sp),sp
move.l d0,-4(a6)
addq.l #8,a4
tst.l -8(a6)
beq.s dop386
moveq.l #$2D,d0
move.b d0,(a2)+
dop386:
movea.l -4(a6),a0
moveq.l #$30,d0
cmp.b (a0),d0
bne.s dop394
addq.l #1,-12(a6)
dop394:
movea.l -4(a6),a0
move.b (a0),(a2)+
addq.l #1,-4(a6)
moveq.l #$2E,d0
move.b d0,(a2)+
move.l d4,d6
bra.s dop3b0
dop3a6:
movea.l -4(a6),a0
move.b (a0),(a2)+
addq.l #1,-4(a6)
dop3b0:
subq.l #1,d6
bgt.s dop3a6
moveq.l #$65,d0
move.b d0,(a2)+
subq.l #1,-12(a6)
tst.l -12(a6)
blt.s dop3c8
moveq.l #$2B,d0 * put a + sign if we need one.
move.b d0,(a2)+
bra.s dop3d6
dop3c8:
moveq.l #$2D,d0 * or a - sign.
move.b d0,(a2)+
move.l -12(a6),d0
neg.l d0
move.l d0,-12(a6)
dop3d6:
moveq.l #$64,d0 * here we make ascii digits by
move.l d0,(sp) * repeatedly hacking them off by
move.l -12(a6),-(sp) * dividing by 100.
jsr _uldivr
addq.l #4,sp
move.l d0,d6
beq.s dop3f2
move.l d6,d0
moveq.l #$30,d1 * add ascii 0 to value so user
add.l d1,d0 * can read it and put it in the
move.b d0,(a2)+ * output buffer.
dop3f2:
moveq.l #$A,d0 * multiply remainder by 10
move.l d0,(sp)
move.l _ldivrm,-(sp)
jsr _uldivr
addq.l #4,sp
move.l d0,d6
beq.s dop410
move.l d6,d0
moveq.l #$30,d1 * add ascii 0 to it too.
add.l d1,d0
move.b d0,(a2)+
dop410:
move.l _ldivrm,d0 * do the remainder too.
moveq.l #$30,d1
add.l d1,d0
move.b d0,(a2)+
bra.l dop250 * go around again for next one.
dop420:
tst.b -153(a6)
bne.s dop428
moveq.l #6,d4 * defaults to 6 digits if no
* * precision was specified.
dop428:
move.l a2,(sp)
move.l d4,-(sp)
move.l 4(a4),-(sp)
move.l (a4),-(sp)
jsr _gcvt * handle g format output.
lea 12(sp),sp * not much work here, gcvt does it
addq.l #8,a4 * all for us.
dop43e:
nop * needed because of bug in Amiga
tst.b (a2)+ * assembler which won't let us do
bne.s dop43e * a short branch to dop43e. We
subq.l #1,a2 * should be able to.
bra.l dop250 * backup over null byte from gcvt.
dop448:
moveq.l #$25,d0 * here is where we output literal %
move.b d0,(a2)+
dop44c:
move.b (a5)+,d7 * move next char from format string
bne.l dop28 * into d7 to be processed.
lea -140(a6),a0
cmpa.l a0,a2 * have we done anything yet?
beq.s dop474 * if no, then skip next part.
move.l a3,(sp) * we must have some chars ready
moveq.l #0,d0 * so call __strout and let it put
move.l d0,-(sp) * them wherever we are supposed to.
lea -140(a6),a0
move.l a2,d0
sub.l a0,d0
move.l d0,-(sp)
pea -140(a6)
bsr.s __strout * go.
lea 12(sp),sp
dop474:
addq.l #4,sp * we are done!. Whew!
movem.l (sp)+,a5-a2/d7-d2
unlk a6
rts
*
* strout modified from SUN version to take into account the differences
* in the structure of __iob on the two machines.
*
__strout:
link a6,#0
movem.l d0/d6-d7/a4-a5,-(sp)
movea.l 8(a6),a5 * some var from doprnt
move.l 12(a6),d7 * length of str to print
move.l 16(a6),d6 * 0 ?
movea.l 20(a6),a4 * address of stdout's iobuf
bra.s str5e
str1e:
move.l a4,(sp)
move.b (a5)+,d0
ext.w d0
ext.l d0
move.l d0,-(sp)
jsr __flsbf
addq.l #4,sp
str30:
subq.l #1,d7
str32:
subq.l #1,4(a4) * modified to subtract from wcnt?
blt.s str4e * it used to read subq.l #1,(a4)
move.l 24(a6),d0
move.l 8(a4),d1 * modified to access the *base of __iob
addq.l #1,8(a4) * this modified too, from 4 to 8.
movea.l d1,a0
move.b d0,(a0)
move.b (a0),d0
ext.w d0
ext.l d0
bra.s str5c
str4e:
move.l a4,(sp) * got some chars so flush the buffer.
move.l 24(a6),-(sp)
jsr __flsbf
addq.l #4,sp
str5c:
addq.l #1,d6
str5e:
tst.l d6
bge.l strbe
moveq.l #$2D,d0
cmp.b (a5),d0
bne.s str32
moveq.l #$30,d0
cmp.l 24(a6),d0
bne.s str32
subq.l #1,4(a4) * modified from subq.l #1,(a4)
blt.s str1e
move.b (a5)+,d0
ext.w d0
ext.l d0
move.l 8(a4),d1 * modified from move.l 4(a4),d1
addq.l #1,8(a4) * modified from addq.l #1,4(a4)
movea.l d1,a0
move.b d0,(a0)
move.b (a0),d0
ext.w d0
ext.l d0
bra.s str30
str8e:
move.b (a5)+,d0
ext.w d0
ext.l d0
move.l 8(a4),d1 * modified from move.l 4(a4),d1
addq.l #1,8(a4) * modified from addq.l #1,4(a4)
movea.l d1,a0
move.b d0,(a0)
move.b (a0),d0
ext.w d0
ext.l d0
bra.s strbe
stra8:
subq.l #1,4(a4) * modified from subq.l #1,(a4)
bge.s str8e
move.l a4,(sp)
move.b (a5)+,d0
ext.w d0
ext.l d0
move.l d0,-(sp)
jsr __flsbf
addq.l #4,sp
strbe:
subq.l #1,d7
bge.s stra8
bra.s strf0
strc4:
subq.l #1,4(a4) * modified from subq.l #1,(a4)
blt.s stre0
move.l 24(a6),d0
move.l 8(a4),d1 * modified from move.l 4(a4),d1
addq.l #1,8(a4) * modified from addq.l #1,4(a4)
movea.l d1,a0
move.b d0,(a0)
move.b (a0),d0
ext.w d0
ext.l d0
bra.s stree
stre0:
move.l a4,(sp)
move.l 24(a6),-(sp)
jsr __flsbf
addq.l #4,sp
stree:
subq.l #1,d6
strf0:
tst.l d6
bne.s strc4
addq.l #4,sp
movem.l (sp)+,a6-a4/d7-d6
rts
*
* support routine. Do unsigned long divide with remainder. remainder is
* left in location _ldivrm.
*
_uldivr:
moveq.l #0,d1
move.w 4(sp),d1
divu 10(sp),d1
move.w d1,d0
move.w 6(sp),d1
divu 10(sp),d1
swap d0
move.w d1,d0
clr.w d1
swap d1
move.l d1,_ldivrm
rts
*
* implementation of the gcvt() library routine. (See gcvt(3C) for details.)
*
* gcvt uses a user provided buffer unlike ecvt and fcvt which use a static
* buffer that is overwritten with each call. Unfortunately gcvt calls
* ecvt so that if you are mixing calls to ecvt and gcvt your last result
* from ecvt will still be overwritten when you call gcvt. Tough toenails!
*
_gcvt:
link a6,#-12
movem.l d0/d7/a4-a5,-(sp)
pea -4(a6)
pea -8(a6)
move.l 16(a6),-(sp)
move.l 12(a6),-(sp)
move.l 8(a6),-(sp)
jsr _ecvt * let ecvt have its shot at it first.
lea 20(sp),sp
movea.l d0,a5 * address of the result buf.
movea.l 20(a6),a4
tst.l -4(a6)
beq.s gcv3a
moveq.l #$2D,d0
move.b d0,(a4)+
gcv3a:
move.l 16(a6),d0
subq.l #1,d0
move.l d0,d7
bra.s gcv52
gcv44:
moveq.l #$30,d0
cmp.b 0(a5,d7.l),d0
bne.s gcv56
subq.l #1,16(a6)
subq.l #1,d7
gcv52:
tst.l d7
bgt.s gcv44
gcv56:
tst.l -8(a6)
blt.s gcv6a
move.l -8(a6),d0
sub.l 16(a6),d0 * see if there is enough precision
moveq.l #4,d1 * in the -ddd.ddd format, otherwise
cmp.l d0,d1 * we'll have to use scientific
blt.s gcv78 * notation.
gcv6a:
tst.l -8(a6)
bge.l gcve8
moveq.l #-3,d0 * if exponent <= -4 then we need
cmp.l -8(a6),d0 * to use e format to get the
ble.l gcve8 * maximum precision.
gcv78:
subq.l #1,-8(a6)
move.b (a5)+,(a4)+
moveq.l #$2E,d0 * ecvt doesn't put in decimal point
move.b d0,(a4)+ * so we have to do it ourselves.
moveq.l #1,d7
bra.s gcv8a
gcv86:
move.b (a5)+,(a4)+
addq.l #1,d7
gcv8a:
cmp.l 16(a6),d7
blt.s gcv86
moveq.l #$65,d0
move.b d0,(a4)+
tst.l -8(a6)
bge.s gcva8
move.l -8(a6),d0
neg.l d0 * negate the number and put in our
move.l d0,-8(a6) * own minus sign.
moveq.l #$2D,d0 * minus sign is aimed and ready!
move.b d0,(a4)+
moveq.l #$A,d0
move.l d0,(sp)
move.l -8(a6),-(sp)
jsr ldivll
addq.l #4,sp
tst.l d0
ble.s gcvd2
gcva8:
moveq.l #$A,d0
move.l d0,(sp)
move.l -8(a6),-(sp)
jsr ldivll
addq.l #4,sp
moveq.l #$30,d1
add.l d1,d0
move.b d0,(a4)+
gcvd2:
moveq.l #$A,d0
move.l d0,(sp)
move.l -8(a6),-(sp)
jsr lremll
addq.l #4,sp
moveq.l #$30,d1
add.l d1,d0
bra.l gcv13c
gcve8:
tst.l -8(a6)
bgt.s gcvfc
moveq.l #$30,d0
move.b d0,(a4)+
moveq.l #$2E,d0
gcvf4:
move.b d0,(a4)+
tst.l -8(a6)
blt.s gcv100
gcvfc:
moveq.l #1,d7
bra.s gcv116
gcv100:
addq.l #1,-8(a6)
moveq.l #$30,d0
bra.s gcvf4
gcv108:
move.b (a5)+,(a4)+
cmp.l -8(a6),d7
bne.s gcv114
moveq.l #$2E,d0
move.b d0,(a4)+
gcv114:
addq.l #1,d7
gcv116:
cmp.l 16(a6),d7
ble.s gcv108
move.l 16(a6),d0
cmp.l -8(a6),d0
blt.s gcv12c
bra.s gcv13e
gcv128:
moveq.l #$30,d0
move.b d0,(a4)+
gcv12c:
move.l 16(a6),d0
addq.l #1,16(a6)
cmp.l -8(a6),d0
blt.s gcv128
moveq.l #$2E,d0
gcv13c:
move.b d0,(a4)+
gcv13e:
moveq.l #$2E,d0
cmp.b -1(a4),d0
bne.s gcv14a
moveq.l #$30,d0
move.b d0,(a4)+
gcv14a:
moveq.l #0,d0
move.b d0,(a4)
move.l 20(a6),d0
addq.l #4,sp
movem.l (sp)+,a5-a4/d7
unlk a6
rts
*
* support routine for gcvt.
* does long divides. (i.e. 32 bit divides)
ldivll:
lea 4(sp),a0
movem.l d2-d4,-(sp)
move.l #1,d4
move.l (a0),d0
bge.s ldv1a
neg.l d0
neg.w d4
ldv1a:
move.l d0,d2
move.l 20(sp),d1
bge.s ldv26
neg.l d1
neg.w d4
ldv26:
move.l d1,d3
cmpi.l #$10000,d1
bge.s ldv44
clr.w d0
swap d0
divu d1,d0
move.w d0,d3
move.w d2,d0
divu d1,d0
swap d0
move.w d3,d0
swap d0
bra.s ldv6c
ldv44:
lsr.l #1,d0
lsr.l #1,d1
cmpi.l #$10000,d1
bge.s ldv44
divu d1,d0
andi.l #$FFFF,d0
move.l d3,d1
swap d1
mulu d0,d1
swap d1
clr.w d1
mulu d0,d3
add.l d3,d1
cmp.l d1,d2
bge.s ldv6c
subq.l #1,d0
ldv6c:
tst.w d4
bge.s ldv72
neg.l d0
ldv72:
move.l d0,(a0)
movem.l (sp)+,d4-d2
rts
_ldivrm: DC.L 0
*
* support routine for gcvt.
* does long remainders, (mod function.)
*
lremll:
lea 4(sp),a0
movem.l d2-d4,-(sp)
moveq.l #1,d4
move.l (a0),d0
bge.s lrm16
neg.l d0
neg.l d4
lrm16:
move.l d0,d2
move.l 20(sp),d1
bge.s lrm20
neg.l d1
lrm20:
cmpi.l #$10000,d1
bge.s lrm5
clr.w d0
swap d0
divu d1,d0
move.w d2,d0
divu d1,d0
clr.w d0
swap d0
bra.s lrm4
lrm5:
move.l d1,d3
lrm3:
lsr.l #1,d0
lsr.l #1,d1
cmpi.l #$10000,d1
bge.s lrm3
divu d1,d0
move.l d3,d1
swap d1
mulu d0,d1
mulu d3,d0
swap d0
add.l d1,d0
swap d0
cmp.l d0,d2
bge.s lrm2
sub.l d3,d0
lrm2:
sub.l d2,d0
neg.l d0
lrm4:
tst.w d4
bge.s lrm1
neg.l d0
lrm1:
move.l d0,(a0)
movem.l (sp)+,d4-d2
rts
*
* JUNK used by __doprnt on occasion.
*
__lastbuf:
DC.L 0
DC.B '(nul'
DC.B 'l)'
DC.B 0
DC.B 0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
DC.L 0,0,0,0,0,0,0,0,0,0
END